package com.onluy.frameworkcloud.batis.tools.util;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;
import com.onluy.frameworkcloud.batis.holder.ResultMapHolder;
import com.onluy.frameworkcloud.data.entity.BaseEntity;
import com.onluy.frameworkcloud.data.entity.Entity;

public abstract class ResultMapUtil
{
    public static final String MODIFIED_SUFFIX = "-Modified";

    public static void resolveResultMap(MappedStatement ms)
    {
        if (ResultMapHolder.get() != null) {
            return;
        }
        Configuration configuration = ms.getConfiguration();
        List resultMaps = ms.getResultMaps();
        if (resultMaps.size() > 0) {
            ResultMap resultMap = (ResultMap)resultMaps.get(0);
            String id = resultMap.getId();
            Class resultType = resultMap.getType();
            if (Entity.class.isAssignableFrom(resultType)) {
                List newResultMaps = new ArrayList();
                List newResultMappings = new ArrayList();
                Map fields = EntityUtil.getAllColumnFields(resultType);
                boolean modify = false;
                for (Object column : fields.keySet()) {
                    Field field = (Field)fields.get(column);
                    ResultMapping resultMapping = getResultMapping(resultMap, column.toString());
                    if (resultMapping == null)
                    {
                        ResultMapping.Builder builder = new ResultMapping.Builder(configuration, field.getName(), column.toString(), field.getType());
                        builder.lazy(configuration.isLazyLoadingEnabled());
                        newResultMappings.add(builder.build());
                        modify = true;
                    }
                    else {
                        newResultMappings.add(resultMapping);
                    }
                }
                if (modify) {
                    ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(configuration, id + "-Modified", resultType, newResultMappings, null);
                    newResultMaps.add(inlineResultMapBuilder.build());

                    ResultMapHolder.set(newResultMaps);
                }
            }
        }
    }

    public static void resolveResultMapByEntity(MappedStatement ms, Class<? extends BaseEntity> clazz)
    {
        if (ResultMapHolder.get() != null) {
            return;
        }
        Configuration configuration = ms.getConfiguration();
        List resultMaps = ms.getResultMaps();
        if (resultMaps.size() > 0) {
            ResultMap resultMap = (ResultMap)resultMaps.get(0);
            String id = resultMap.getId();
            Class resultType = resultMap.getType();
            if (!clazz.equals(resultType)) {
                List newResultMaps = new ArrayList();
                List newResultMappings = new ArrayList();
                Map fields = EntityUtil.getAllColumnFields(clazz);
                for (Object column : fields.keySet()) {
                    Field field = (Field)fields.get(column);
                    ResultMapping.Builder builder = new ResultMapping.Builder(configuration, field.getName(), column.toString(), field.getType());
                    builder.lazy(configuration.isLazyLoadingEnabled());
                    newResultMappings.add(builder.build());
                }
                ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(configuration, id + "-Modified", clazz, newResultMappings, null);
                newResultMaps.add(inlineResultMapBuilder.build());

                ResultMapHolder.set(newResultMaps);
            }
        }
    }

    public static void resolveResultMapCount(MappedStatement ms)
    {
        if (ResultMapHolder.get() != null) {
            return;
        }
        Configuration configuration = ms.getConfiguration();
        ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(configuration, ms.getId() + "-Inline" + "-Modified", Long.class, new ArrayList(), null);
        List resultMaps = new ArrayList();
        resultMaps.add(inlineResultMapBuilder.build());

        ResultMapHolder.set(resultMaps);
    }

    private static ResultMapping getResultMapping(ResultMap resultMap, String column)
    {
        for (ResultMapping resultMapping : resultMap.getResultMappings()) {
            if (column.equals(resultMapping.getColumn())) {
                return resultMapping;
            }
        }
        return null;
    }
}